<!--
 * @Author: Lijie
 * @Date: 2023-12-11
-->
<template>
  <view class="select-wrap">
    <view
      class="input"
      :class="[!currentLabel ? 'placeholder' : '', border ? 'border' : '', validateStatus]"
      :style="'justify-content:' + align"
      @click="showDialog"
    >
      <text class="label">{{ currentLabel || placeholder }}</text>
      <text class="arrow cuIcon-right"></text>
    </view>
    <block v-if="show">
      <view class="mask" :class="visible ? 'on' : ''" @click="closeHandle"></view>
      <view class="picker-wrap" :class="visible ? 'on' : ''">
        <view class="header">
          <view class="cancel text-gray" @click="closeHandle">取消</view>
          <view v-if="placeholder">{{ placeholder }}</view>
          <view class="ok text-blue" @click="done">确定</view>
        </view>
        <picker-view
          :indicator-style="indicatorStyle"
          v-bind:value="currentPicker"
          @change="change"
          :immediate-change="true"
          class="picker-view"
        >
          <picker-view-column style="padding-left: 10rpx">
            <view class="item" v-for="(item, index) in options" :key="index">
              {{ item[kv.label] }}
            </view>
          </picker-view-column>
        </picker-view>
      </view>
    </block>
  </view>
</template>

<script lang="ts" setup name="ThSelect">
const props = defineProps({
  placeholder: {
    type: String,
    default: '请选择',
  },
  options: {
    type: Array,
    default: () => {
      return [];
    },
  },
  kv: {
    type: Object,
    default: () => {
      return {
        label: 'label',
        value: 'value',
      };
    },
  },
  value: {
    type: [String, Number],
  },
  limit: {
    type: Object,
  },
  align: {
    type: String,
    default: 'space-between',
  },
  border: {
    type: [Boolean, String],
    default: false,
  },
  disabled: {
    type: [Boolean, String],
    default: false,
  },
  validate: {
    type: Array,
    default: () => {
      return [];
    },
  },
});

const emit = defineEmits(['update:value', 'change']);

const show = ref(false);
const visible = ref(false);
const indicatorStyle = ref('height: 50px;');
const currentPicker = ref([0]);
const currentValue = ref('');
const tempPicker = ref([0]);
const currentLabel = ref('');

const showDialog = () => {
  show.value = true;
  nextTick(() => {
    visible.value = true;
  });
};
const closeHandle = () => {
  visible.value = false;
  setTimeout(() => {
    show.value = false;
  }, 200);
};
const change = (e) => {
  tempPicker.value = e.detail.value;
};
const done = () => {
  if (props.options.length) {
    currentPicker.value = tempPicker.value;
    const data = props.options[currentPicker.value[0]];
    emit('update:value', data[props.kv.value]);
    emit('change', data);
    currentLabel.value = data[props.kv.label];
  }
  closeHandle();
};

watch(
  [() => props.value, () => props.options],
  (n) => {
    const [value, options] = n;
    if (value || value === 0) {
      options.forEach((opt: any, index) => {
        if (opt.value === value) {
          currentPicker.value = [index];
          tempPicker.value = [index];
          currentValue.value = opt[props.kv.value];
          currentLabel.value = opt[props.kv.label];
        }
      });
    } else {
      currentPicker.value = [0];
      tempPicker.value = [0];
      currentValue.value = '';
      currentLabel.value = '';
    }
  },
  {
    immediate: true,
    deep: true,
  },
);

const validateStatus = ref('');
const modelValue = computed({
  get: () => {
    return props.value;
  },
  set: (val) => {
    emit('update:value', val);
  },
});
watch(
  () => props.value,
  (val) => {
    validate(val);
  },
);

const validate = (val = modelValue.value) => {
  let valid = true;
  props.validate.forEach((rule: any) => {
    if (rule.trigger === 'change') {
      if (rule.required) {
        if (!val) {
          validateStatus.value = 'error';
          valid = false;
        } else {
          validateStatus.value = '';
          valid = true;
        }
      }
    }
  });
  return valid;
};
defineExpose({ validate });
</script>

<style lang="scss" scoped>
.select-wrap {
  flex: 1;
  .placeholder {
    color: #bfbfbf;
    font-size: 30rpx;
  }
  .input {
    display: flex;
    padding-left: 20rpx;
    align-items: center;
    height: 60rpx;
    line-height: 60rpx;
    border-radius: 8rpx;
    .label {
      height: 100%;
      flex: 1;
      white-space: no-wrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
    &.border {
      border: 1px solid #dcdfe6;
      &.error {
        border: 1px solid red !important;
      }
    }
  }
  .arrow {
    font-size: 28rpx;
    color: #dcdfe6;
    font-size: 30rpx;
    width: 60rpx;
    text-align: center;
  }
}
.mask {
  position: fixed;
  width: 100vw;
  height: 100vh;
  bottom: 0;
  left: 0;
  visibility: hidden;
  z-index: 999998;
  background: rgba(0, 0, 0, 0);
  transition: all 0.3s;
  &.on {
    background: rgba(0, 0, 0, 0.5);
    visibility: visible;
  }
}
.picker-wrap {
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 999999;
  width: 100vw;
  border-top-right-radius: 5rpx;
  border-top-left-radius: 5rpx;
  overflow: hidden;
  transform: translateY(100%);
  transition: all 0.15s ease-in-out;
  &.on {
    transform: translateY(0);
  }
  .header {
    display: flex;
    justify-content: space-between;
    height: 100rpx;
    background: #fff;
    line-height: 100rpx;
    padding: 0 30rpx;
    font-size: 30rpx;
    border-bottom: 1rpx solid #f1f1f1;
  }
  .picker-view {
    width: 100vw;
    height: 600rpx;
    background-color: #fff;
    font-size: 38rpx;
  }
  .item {
    width: 100%;
    height: 50px;
    line-height: 50px;
    align-items: center;
    justify-content: center;
    text-align: center;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    text {
      font-size: 26rpx;
      margin-left: 5rpx;
      color: #333;
    }
  }
}
</style>
